home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Mail / pine3.92 / pico / file.c < prev    next >
C/C++ Source or Header  |  1996-03-16  |  24KB  |  929 lines

  1. #if    !defined(lint) && !defined(DOS)
  2. static char rcsid[] = "$Id: file.c,v 4.39 1996/03/17 02:54:19 mikes Exp $";
  3. #endif
  4. /*
  5.  * Program:    High level file input and output routines
  6.  *
  7.  *
  8.  * Michael Seibel
  9.  * Networks and Distributed Computing
  10.  * Computing and Communications
  11.  * University of Washington
  12.  * Administration Builiding, AG-44
  13.  * Seattle, Washington, 98195, USA
  14.  * Internet: mikes@cac.washington.edu
  15.  *
  16.  * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
  17.  *
  18.  *
  19.  * Pine and Pico are registered trademarks of the University of Washington.
  20.  * No commercial use of these trademarks may be made without prior written
  21.  * permission of the University of Washington.
  22.  * 
  23.  * Pine, Pico, and Pilot software and its included text are Copyright
  24.  * 1989-1996 by the University of Washington.
  25.  * 
  26.  * The full text of our legal notices is contained in the file called
  27.  * CPYRIGHT, included with this distribution.
  28.  *
  29.  */
  30. /*
  31.  * The routines in this file
  32.  * handle the reading and writing of
  33.  * disk files. All of details about the
  34.  * reading and writing of the disk are
  35.  * in "fileio.c".
  36.  */
  37. #include        <stdio.h>
  38. #include    "osdep.h"
  39. #include        "pico.h"
  40. #include    "estruct.h"
  41. #include        "edef.h"
  42. #include        "efunc.h"
  43.  
  44.  
  45. #ifdef    ANSI
  46.     int ifile(char *);
  47.     int insmsgchar(int);
  48. #else
  49.     int ifile();
  50.     int insmsgchar();
  51. #endif
  52.  
  53.  
  54. /*
  55.  * Read a file into the current
  56.  * buffer. This is really easy; all you do it
  57.  * find the name of the file, and call the standard
  58.  * "read a file into the current buffer" code.
  59.  * Bound to "C-X C-R".
  60.  */
  61. fileread(f, n)
  62. int f, n;
  63. {
  64.         register int    s;
  65.         char fname[NFILEN];
  66.  
  67.         if ((s=mlreply("Read file: ", fname, NFILEN, QNORML, NULL)) != TRUE)
  68.                 return(s);
  69.  
  70.     if(gmode&MDSCUR){
  71.         emlwrite("File reading disabled in secure mode",NULL);
  72.         return(0);
  73.     }
  74.  
  75.     if (strlen(fname) == 0) {
  76.       emlwrite("No file name entered",NULL);
  77.       return(0);
  78.     }
  79.  
  80.     if((gmode&MDTREE) && !in_oper_tree(fname)){
  81.       emlwrite("Can't read file from outside of %s", opertree);
  82.       return(0);
  83.     }
  84.  
  85.         return(readin(fname, TRUE));
  86. }
  87.  
  88.  
  89.  
  90.  
  91. static char *inshelptext[] = {
  92.   "Insert File Help Text",
  93.   " ",
  94.   "\tType in a file name to have it inserted into your editing",
  95.   "\tbuffer between the line that the cursor is currently on",
  96.   "\tand the line directly below it.  You may abort this by ",
  97.   "~\ttyping the ~F~2 (~^~C) key after exiting help.",
  98.   " ",
  99.   "End of Insert File Help",
  100.   " ",
  101.   NULL
  102. };
  103.  
  104. static char *writehelp[] = {
  105.   "Write File Help Text",
  106.   " ",
  107.   "\tType in a file name to have it written out, thus saving",
  108.   "\tyour buffer, to a file.  You can abort this by typing ",
  109.   "~\tthe ~F~2 (~^~C) key after exiting help.",
  110.   " ",
  111.   "End of Write File Help",
  112.   " ",
  113.   " ",
  114.   NULL
  115. };
  116.  
  117.  
  118. /*
  119.  * Insert a file into the current
  120.  * buffer. This is really easy; all you do it
  121.  * find the name of the file, and call the standard
  122.  * "insert a file into the current buffer" code.
  123.  * Bound to "C-X C-I".
  124.  */
  125. insfile(f, n)
  126. int f, n;
  127. {
  128.     register int s;
  129.     char     fname[NFILEN], dir[NFILEN];
  130.     int         retval, bye = 0, msg = 0;
  131.     char     prompt[64];
  132.     EXTRAKEYS    menu_ins[5];
  133.     
  134.     if (curbp->b_mode&MDVIEW) /* don't allow this command if */
  135.       return(rdonly()); /* we are in read only mode */
  136.  
  137.     fname[0] = '\0';
  138.     while(!bye){
  139.     /* set up keymenu stuff */
  140.     if(!msg){
  141.         int last_menu = 0;
  142.  
  143.         menu_ins[last_menu].name  = "^T";
  144.         menu_ins[last_menu].key   = (CTRL|'T');
  145.         menu_ins[last_menu].label = "To Files";
  146.         KS_OSDATASET(&menu_ins[last_menu], KS_NONE);
  147.  
  148.         if(Pmaster && Pmaster->msgntext){
  149.         menu_ins[++last_menu].name  = "^W";
  150.         menu_ins[last_menu].key     = (CTRL|'W');
  151.         menu_ins[last_menu].label   = msg ? "InsertFile" : "InsertMsg";
  152.         KS_OSDATASET(&menu_ins[last_menu], KS_NONE);
  153.         }
  154.  
  155. #if    !defined(DOS) && !defined(MAC)
  156.         if(Pmaster && Pmaster->upload){
  157.         menu_ins[++last_menu].name = "^Y";
  158.         menu_ins[last_menu].key    = (CTRL|'Y');
  159.         menu_ins[last_menu].label  = "RcvUpload";
  160.         KS_OSDATASET(&menu_ins[last_menu], KS_NONE);
  161.         }
  162. #endif    /* !(DOS || MAC) */
  163.  
  164.         if(gmode & MDCMPLT){
  165.         menu_ins[++last_menu].name = msg ? "" : "TAB";
  166.         menu_ins[last_menu].key    = (CTRL|'I');
  167.         menu_ins[last_menu].label  = msg ? "" : "Complete";
  168.         KS_OSDATASET(&menu_ins[last_menu], KS_NONE);
  169.         }
  170.  
  171.         menu_ins[++last_menu].name = NULL;
  172.     }
  173.  
  174.     sprintf(prompt, "%s to insert from %s %s: ",
  175.         msg ? "Number of message" : "File",
  176.         (msg || (gmode&MDCURDIR)) ? "current"
  177.                       : (gmode&MDTREE) ? opertree
  178.                                : "home",
  179.         msg ? "folder" : "directory");
  180.     s = mlreplyd(prompt, fname, NFILEN, QDEFLT, msg ? NULL : menu_ins);
  181.     /* something to read and it was edited or the default accepted */
  182.         if(fname[0] && (s == TRUE || s == FALSE)){
  183.         bye++;
  184.         if(msg){
  185.         if((*Pmaster->msgntext)(atol(fname), insmsgchar))
  186.           emlwrite("Message %s included", fname);
  187.         }
  188.         else{
  189.         bye++;
  190.         if(gmode&MDSCUR){
  191.             emlwrite("Can't insert file in restricted mode",NULL);
  192.         }
  193.         else{
  194.             if(gmode&MDTREE)
  195.               compresspath(opertree, fname, NFILEN);
  196.  
  197.             fixpath(fname, NFILEN);
  198.             if((gmode&MDTREE) && !in_oper_tree(fname))
  199.               emlwrite("Can't insert file from outside of %s",
  200.                     opertree);
  201.             else
  202.               retval = ifile(fname);
  203.         }
  204.         }
  205.     }
  206.     else{
  207.         switch(s){
  208.           case (CTRL|'I') :
  209.         {
  210.             char *fn, *p;
  211.             int   l = NFILEN;;
  212.  
  213.             dir[0] = '\0';
  214.             if(*fname && (p = strrchr(fname, C_FILESEP))){
  215.             fn = p + 1;
  216.             l -= p - fname;
  217.             if(p == fname)
  218.               strcpy(dir, S_FILESEP);
  219. #ifdef    DOS
  220.             else if(fname[0] == C_FILESEP
  221.                  || (isalpha(fname[0]) && fname[1] == ':')){
  222. #else
  223.             else if (fname[0] == C_FILESEP || fname[0] == '~') {
  224. #endif
  225.                 strncpy(dir, fname, p - fname);
  226.                 dir[p-fname] = '\0';
  227.             }
  228.             else
  229.               sprintf(dir, "%s%c%.*s", 
  230.                   (gmode&MDCURDIR) ? "."
  231.                       : (gmode&MDTREE) ? opertree
  232.                                : gethomedir(NULL),
  233.                   C_FILESEP, p - fname, fname);
  234.             }
  235.             else{
  236.             fn = fname;
  237.             strcpy(dir, gmode&MDCURDIR ? "."
  238.                         : gmode&MDTREE ? opertree
  239.                                : gethomedir(NULL));
  240.             }
  241.  
  242.             if(!pico_fncomplete(dir, fn, l - 1))
  243.               (*term.t_beep)();
  244.         }
  245.  
  246.         break;
  247.           case (CTRL|'W'):
  248.         msg = !msg;            /* toggle what to insert */
  249.         break;
  250.           case (CTRL|'T'):
  251.         if(msg){
  252.             emlwrite("Can't select messages yet!", NULL);
  253.         }
  254.         else{
  255.             if(*fname && isdir(fname, NULL))
  256.               strcpy(dir, fname);
  257.             else
  258.               strcpy(dir, (gmode&MDCURDIR) ? "."
  259.                       : (gmode&MDTREE) ? opertree
  260.                                : gethomedir(NULL));
  261.  
  262.             fname[0] = '\0';
  263.             if((s = FileBrowse(dir, fname, NULL, FB_READ)) == 1){
  264.             if(gmode&MDSCUR){
  265.                 emlwrite("Can't insert in restricted mode",
  266.                      NULL);
  267.                 sleep(2);
  268.             }
  269.             else{
  270.                 strcat(dir, S_FILESEP);
  271.                 strcat(dir, fname);
  272.                 retval = ifile(dir);
  273.             }
  274.             bye++;
  275.             }
  276.             else
  277.               fname[0] = '\0';
  278.  
  279.             refresh(FALSE, 1);
  280.             if(s != 1){
  281.             update();         /* redraw on return */
  282.             continue;
  283.             }
  284.         }
  285.  
  286.         break;
  287.  
  288. #if    !defined(DOS) && !defined(MAC)
  289.           case (CTRL|'Y') :
  290.         if(Pmaster && Pmaster->upload){
  291.             char tfname[NFILEN];
  292.  
  293.             if(gmode&MDSCUR){
  294.             emlwrite(
  295.                   "\007Restricted mode disallows uploaded command",
  296.                   NULL);
  297.             return(0);
  298.             }
  299.  
  300.             tfname[0] = '\0';
  301.             retval = (*Pmaster->upload)(tfname, NULL);
  302.  
  303.             refresh(FALSE, 1);
  304.             update();
  305.  
  306.             if(retval){
  307.             retval = ifile(tfname);
  308.             bye++;
  309.             }
  310.             else
  311.               sleep(3);            /* problem, show error! */
  312.  
  313.             if(tfname[0])        /* clean up temp file */
  314.               unlink(tfname);
  315.         }
  316.         else
  317.           (*term.t_beep)();        /* what? */
  318.  
  319.         break;
  320. #endif    /* !(DOS || MAC) */
  321.           case HELPCH:
  322.         if(Pmaster){
  323.             (*Pmaster->helper)(Pmaster->ins_help,
  324.                        "Help for Insert File", 1);
  325.         }
  326.         else
  327.           pico_help(inshelptext, "Help for Insert File", 1);
  328.           case (CTRL|'L'):
  329.         refresh(FALSE, 1);
  330.         update();
  331.         continue;
  332.           default:
  333.         ctrlg(FALSE, 0);
  334.                 retval = s;
  335.         bye++;
  336.         }
  337.         }
  338.     }
  339.     curwp->w_flag |= WFMODE|WFHARD;
  340.     
  341.     return(retval);
  342. }
  343.  
  344.  
  345. insmsgchar(c)
  346.     int c;
  347. {
  348.     if(c == '\n'){
  349.     char *p;
  350.  
  351.     lnewline();
  352.     for(p = Pmaster->quote_str; p && *p; p++)
  353.       if(!linsert(1, *p))
  354.         return(0);
  355.     }
  356.     else if(c != '\r')            /* ignore CR (likely CR of CRLF) */
  357.       return(linsert(1, c));
  358.  
  359.     return(1);
  360. }
  361.  
  362.  
  363.  
  364. /*
  365.  * Read file "fname" into the current
  366.  * buffer, blowing away any text found there. Called
  367.  * by both the read and find commands. Return the final
  368.  * status of the read. Also called by the mainline,
  369.  * to read in a file specified on the command line as
  370.  * an argument.
  371.  */
  372. readin(fname, lockfl)
  373. char    fname[];    /* name of file to read */
  374. int    lockfl;        /* check for file locks? */
  375. {
  376.         register LINE   *lp1;
  377.         register LINE   *lp2;
  378.         register int    i;
  379.         register WINDOW *wp;
  380.         register BUFFER *bp;
  381.         register int    s;
  382.         register int    nbytes;
  383.         register int    nline;
  384.     register char    *sptr;        /* pointer into filename string */
  385.     int        lflag;        /* any lines longer than allowed? */
  386.         char            line[NLINE];
  387.     CELL            ac;
  388.  
  389.         bp = curbp;                             /* Cheap.               */
  390.     bp->b_linecnt = -1;            /* Must be recalculated */
  391.     ac.a = 0;
  392.         if ((s=bclear(bp)) != TRUE)             /* Might be old.        */
  393.                 return (s);
  394.         bp->b_flag &= ~(BFTEMP|BFCHG);
  395.     /* removed 'C' mode detection */
  396.         strcpy(bp->b_fname, fname);
  397.     if((gmode&MDTREE) && !in_oper_tree(fname)){
  398.         emlwrite("Can't read file from outside of %s", opertree);
  399.         s = FIOERR;
  400.         goto out;
  401.     }
  402.  
  403.         if ((s=ffropen(fname)) != FIOSUC){      /* Hard file open.      */
  404.         if(s == FIOFNF)                     /* File not found.      */
  405.           emlwrite("New file", NULL);
  406.         else
  407.           fioperr(s, fname);
  408.  
  409.         goto out;
  410.     }
  411.  
  412.         emlwrite("Reading file", NULL);
  413.         nline = 0;
  414.     lflag = FALSE;
  415.         while ((s=ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG) {
  416.         if (s == FIOLNG)
  417.             lflag = TRUE;
  418.                 nbytes = strlen(line);
  419.                 if ((lp1=lalloc(nbytes)) == NULL) {
  420.                         s = FIOERR;             /* Keep message on the  */
  421.                         break;                  /* display.             */
  422.                 }
  423.                 lp2 = lback(curbp->b_linep);
  424.                 lp2->l_fp = lp1;
  425.                 lp1->l_fp = curbp->b_linep;
  426.                 lp1->l_bp = lp2;
  427.                 curbp->b_linep->l_bp = lp1;
  428.                 for (i=0; i<nbytes; ++i){
  429.             ac.c = line[i];
  430.             lputc(lp1, i, ac);
  431.         }
  432.                 ++nline;
  433.         }
  434.         ffclose();                              /* Ignore errors.       */
  435.         if (s == FIOEOF) {                      /* Don't zap message!   */
  436.                 sprintf(line,"Read %d line%s", nline, (nline > 1) ? "s" : "");
  437.                 emlwrite(line, NULL);
  438.         }
  439.     if (lflag){
  440.         sprintf(line,"Read %d line%s, Long lines wrapped",
  441.             nline, (nline > 1) ? "s" : "");
  442.                 emlwrite(line, NULL);
  443.         }
  444. out:
  445.         for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
  446.                 if (wp->w_bufp == curbp) {
  447.                         wp->w_linep = lforw(curbp->b_linep);
  448.                         wp->w_dotp  = lforw(curbp->b_linep);
  449.                         wp->w_doto  = 0;
  450.                         wp->w_imarkp = NULL;
  451.                         wp->w_imarko = 0;
  452.  
  453.             if(Pmaster)
  454.               wp->w_flag |= WFHARD;
  455.             else
  456.               wp->w_flag |= WFMODE|WFHARD;
  457.                 }
  458.         }
  459.         if (s == FIOERR || s == FIOFNF)        /* False if error.      */
  460.                 return(FALSE);
  461.         return (TRUE);
  462. }
  463.  
  464.  
  465. /*
  466.  * Ask for a file name, and write the
  467.  * contents of the current buffer to that file.
  468.  * Update the remembered file name and clear the
  469.  * buffer changed flag. This handling of file names
  470.  * is different from the earlier versions, and
  471.  * is more compatable with Gosling EMACS than
  472.  * with ITS EMACS. Bound to "C-X C-W".
  473.  */
  474. filewrite(f, n)
  475. int f, n;
  476. {
  477.         register WINDOW *wp;
  478.         register int    s;
  479.         char            fname[NFILEN];
  480.     char        shows[128], *bufp;
  481.     long        l;        /* length returned from fexist() */
  482.     EXTRAKEYS    menu_write[3];
  483.  
  484.     if(curbp->b_fname[0] != 0)
  485.       strcpy(fname, curbp->b_fname);
  486.     else
  487.       fname[0] = '\0';
  488.  
  489.     menu_write[0].name  = "^T";
  490.     menu_write[0].label = "To Files";
  491.     menu_write[0].key   = (CTRL|'T');
  492.     menu_write[1].name  = "TAB";
  493.     menu_write[1].label = "Complete";
  494.     menu_write[1].key   = (CTRL|'I');
  495.     menu_write[2].name  = NULL;
  496.     for(;!(gmode & MDTOOL);){
  497.         s = mlreplyd("File Name to write : ", fname, NFILEN,
  498.              QDEFLT|QFFILE, menu_write);
  499.  
  500.         switch(s){
  501.           case FALSE:
  502.         if(!fname[0]){            /* no file name to write to */
  503.             ctrlg(FALSE, 0);
  504.             return(s);
  505.         }
  506.           case TRUE:
  507.         if(gmode&MDTREE)
  508.           compresspath(opertree, fname, NFILEN);
  509.  
  510.         fixpath(fname, NFILEN);        /*  fixup ~ in file name  */
  511.         if((gmode&MDTREE) && !in_oper_tree(fname)){
  512.             emlwrite("Can't write outside of %s", opertree);
  513.             sleep(2);
  514.             continue;
  515.         }
  516.         else
  517.           break;
  518.           case (CTRL|'I'):
  519.         {
  520.             char *fn, *p, dir[NFILEN];
  521.             int   l = NFILEN;;
  522.  
  523.             dir[0] = '\0';
  524.             if(*fname && (p = strrchr(fname, C_FILESEP))){
  525.             fn = p + 1;
  526.             l -= p - fname;
  527.             if(p == fname)
  528.               strcpy(dir, S_FILESEP);
  529. #ifdef    DOS
  530.             else if(fname[0] == C_FILESEP
  531.                  || (isalpha(fname[0]) && fname[1] == ':')){
  532. #else
  533.             else if (fname[0] == C_FILESEP || fname[0] == '~') {
  534. #endif
  535.                 strncpy(dir, fname, p - fname);
  536.                 dir[p-fname] = '\0';
  537.             }
  538.             else
  539.               sprintf(dir, "%s%c%.*s", 
  540.                   (gmode&MDCURDIR) ? "."
  541.                       : gmode&MDTREE ? opertree
  542.                              : gethomedir(NULL),
  543.                   C_FILESEP, p - fname, fname);
  544.             }
  545.             else{
  546.             fn = fname;
  547.             strcpy(dir, gmode&MDCURDIR ? "."
  548.                     : gmode&MDTREE ? opertree
  549.                                : gethomedir(NULL));
  550.             }
  551.  
  552.             if(!pico_fncomplete(dir, fn, l - 1))
  553.               (*term.t_beep)();
  554.         }
  555.  
  556.         continue;
  557.           case (CTRL|'T'):
  558.         /* If we have a file name, break up into path and file name.*/
  559.         *shows = 0;
  560.         if(*fname) {
  561.             if (isdir (fname, NULL)) {
  562.             /* fname is a directory. */
  563.             strcpy (shows, fname);
  564.             *fname = '\0';
  565.             }
  566.             else {
  567.             /* Find right most seperator. */
  568.             bufp = strrchr (fname, C_FILESEP);
  569.             if (bufp != NULL) {
  570.                 /* Copy directory part to 'shows', and file
  571.                  * name part to front of 'fname'. */
  572.                 *bufp = '\0';
  573.                 strcpy (shows, fname);
  574.                 memcpy (fname, bufp+1, strlen (bufp+1) + 1);
  575.             }
  576.             }
  577.         }
  578.  
  579.         /* If we did not end up with a valid directory, use home. */
  580.         if (!*shows || !isdir (shows, NULL))
  581.           strcpy(shows, (gmode&MDTREE) ? opertree : gethomedir(NULL));
  582.  
  583.         s = FileBrowse(shows, fname, NULL, FB_SAVE);
  584.         strcat(shows, S_FILESEP);
  585.         strcat(shows, fname);
  586.         strcpy(fname, shows);
  587.  
  588.         refresh(FALSE, 1);
  589.         update();
  590.         if(s == 1)
  591.           break;
  592.         else
  593.           continue;
  594.           case HELPCH:
  595.         pico_help(writehelp, "", 1);
  596.           case (CTRL|'L'):
  597.         refresh(FALSE, 1);
  598.         update();
  599.         continue;
  600.           default:
  601.         return(s);
  602.         break;
  603.         }
  604.  
  605.         if(strcmp(fname, curbp->b_fname) == 0)
  606.         break;
  607.  
  608.         if((s=fexist(fname, "w", &l)) == FIOSUC){ /* exists.  overwrite? */
  609.  
  610.         sprintf(shows, "File \"%s\" exists, OVERWRITE", fname);
  611.         if((s=mlyesno(shows, FALSE)) == TRUE)
  612.           break;
  613.         }
  614.         else if(s == FIOFNF){
  615.         break;                /* go write it */
  616.         }
  617.         else{                /* some error, can't write */
  618.         fioperr(s, fname);
  619.         return(ABORT);
  620.         }
  621.     }
  622.     emlwrite("Writing...", NULL);
  623.  
  624.         if ((s=writeout(fname)) != -1) {
  625.             if(!(gmode&MDTOOL)){
  626.             strcpy(curbp->b_fname, fname);
  627.             curbp->b_flag &= ~BFCHG;
  628.  
  629.             wp = wheadp;                    /* Update mode lines.   */
  630.             while (wp != NULL) {
  631.                         if (wp->w_bufp == curbp)
  632.                 if((Pmaster && s == TRUE) || Pmaster == NULL)
  633.                                 wp->w_flag |= WFMODE;
  634.                         wp = wp->w_wndp;
  635.             }
  636.         }
  637.  
  638.         if(s > 1)
  639.           emlwrite("Wrote %d lines", (void *)s);
  640.         else
  641.           emlwrite("Wrote 1 line", NULL);
  642.         }
  643.         return ((s == -1) ? FALSE : TRUE);
  644. }
  645.  
  646.  
  647.  
  648. /*
  649.  * Save the contents of the current
  650.  * buffer in its associatd file. No nothing
  651.  * if nothing has changed (this may be a bug, not a
  652.  * feature). Error if there is no remembered file
  653.  * name for the buffer. Bound to "C-X C-S". May
  654.  * get called by "C-Z".
  655.  */
  656. filesave(f, n)
  657. int f, n;
  658. {
  659.         register WINDOW *wp;
  660.         register int    s;
  661.  
  662.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  663.         return(rdonly());    /* we are in read only mode    */
  664.         if ((curbp->b_flag&BFCHG) == 0)         /* Return, no changes.  */
  665.                 return (TRUE);
  666.         if (curbp->b_fname[0] == 0) {           /* Must have a name.    */
  667.                 emlwrite("No file name", NULL);
  668.         sleep(2);
  669.                 return (FALSE);
  670.         }
  671.  
  672.     emlwrite("Writing...", NULL);
  673.         if ((s=writeout(curbp->b_fname)) != -1) {
  674.                 curbp->b_flag &= ~BFCHG;
  675.                 wp = wheadp;                    /* Update mode lines.   */
  676.                 while (wp != NULL) {
  677.                         if (wp->w_bufp == curbp)
  678.               if(Pmaster == NULL)
  679.                                 wp->w_flag |= WFMODE;
  680.                         wp = wp->w_wndp;
  681.                 }
  682.         if(s > 1){
  683.             emlwrite("Wrote %d lines", (void *)s);
  684.         }
  685.         else
  686.           emlwrite("Wrote 1 line", NULL);
  687.         }
  688.         return (s);
  689. }
  690.  
  691. /*
  692.  * This function performs the details of file
  693.  * writing. Uses the file management routines in the
  694.  * "fileio.c" package. The number of lines written is
  695.  * displayed. Sadly, it looks inside a LINE; provide
  696.  * a macro for this. Most of the grief is error
  697.  * checking of some sort.
  698.  *
  699.  * CHANGES: 1 Aug 91: returns number of lines written or -1 on error, MSS
  700.  */
  701. writeout(fn)
  702. char    *fn;
  703. {
  704.         register int    s;
  705.         register LINE   *lp;
  706.         register int    nline;
  707.     char     line[80];
  708.  
  709.         if ((s=ffwopen(fn)) != FIOSUC)          /* Open writes message. */
  710.                 return (-1);
  711.  
  712.         lp = lforw(curbp->b_linep);             /* First line.          */
  713.         nline = 0;                              /* Number of lines.     */
  714.         while (lp != curbp->b_linep) {
  715.                 if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
  716.                         break;
  717.                 ++nline;
  718.                 lp = lforw(lp);
  719.         }
  720.         if (s == FIOSUC) {                      /* No write error.      */
  721.                 s = ffclose();
  722.         } else                                  /* Ignore close error   */
  723.                 ffclose();                      /* if a write error.    */
  724.         if (s != FIOSUC)                        /* Some sort of error.  */
  725.                 return (-1);
  726.         return (nline);
  727. }
  728.  
  729.  
  730. /*
  731.  * writetmp - write a temporary file for message text, mindful of 
  732.  *          access restrictions and included text.  If n is true, include
  733.  *          lines that indicated included message text, otw forget them
  734.  */
  735. char *writetmp(f, n)
  736. int f, n;
  737. {
  738.         static   char    fn[NFILEN];
  739.         register int    s;
  740.         register LINE   *lp;
  741.         register int    nline;
  742.  
  743.     tmpname(fn);
  744.     
  745.         if ((s=ffwopen(fn)) != FIOSUC)          /* Open writes message. */
  746.                 return(NULL);
  747.  
  748. #ifdef    MODE_READONLY
  749.     chmod(fn, MODE_READONLY);        /* fix access rights */
  750. #endif
  751.  
  752.         lp = lforw(curbp->b_linep);             /* First line.          */
  753.         nline = 0;                              /* Number of lines.     */
  754.         while (lp != curbp->b_linep) {
  755.         if(n || (!n && lp->l_text[0].c != '>'))
  756.                 if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
  757.                         break;
  758.                 ++nline;
  759.                 lp = lforw(lp);
  760.         }
  761.         if (s == FIOSUC) {                      /* No write error.      */
  762.                 s = ffclose();
  763.         } else                                  /* Ignore close error   */
  764.                 ffclose();                      /* if a write error.    */
  765.         if (s != FIOSUC){                       /* Some sort of error.  */
  766.             unlink(fn);
  767.                 return(NULL);
  768.     }
  769.         return(fn);
  770. }
  771.  
  772.  
  773. /*
  774.  * Insert file "fname" into the current
  775.  * buffer, Called by insert file command. Return the final
  776.  * status of the read.
  777.  */
  778. ifile(fname)
  779. char    fname[];
  780. {
  781.         register LINE   *lp0;
  782.         register LINE   *lp1;
  783.         register LINE   *lp2;
  784.         register int    i;
  785.         register BUFFER *bp;
  786.         register int    s;
  787.         register int    nbytes;
  788.         register int    nline;
  789.     int        lflag;        /* any lines longer than allowed? */
  790.         char            line[NLINE];
  791.         char     dbuf[128];
  792.         register char    *dbufp;
  793.     CELL            ac;
  794.  
  795.         bp = curbp;                             /* Cheap.               */
  796.         bp->b_flag |= BFCHG;            /* we have changed    */
  797.     bp->b_flag &= ~BFTEMP;            /* and are not temporary*/
  798.     bp->b_linecnt = -1;            /* must be recalculated */
  799.     ac.a = 0;
  800.         if ((s=ffropen(fname)) != FIOSUC){      /* Hard file open.      */
  801.         fioperr(s,fname);
  802.                 return(FALSE);
  803.     }
  804.  
  805.         emlwrite("Inserting %s.", fname);
  806.  
  807.     /* back up a line and save the mark here */
  808.     curwp->w_dotp = lback(curwp->w_dotp);
  809.     curwp->w_doto = 0;
  810.     curwp->w_imarkp = curwp->w_dotp;
  811.     curwp->w_imarko = 0;
  812.  
  813.         nline = 0;
  814.     lflag = FALSE;
  815.         while ((s=ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG) {
  816.         if (s == FIOLNG)
  817.             lflag = TRUE;
  818.                 nbytes = strlen(line);
  819.                 if ((lp1=lalloc(nbytes)) == NULL) {
  820.                         s = FIOERR;             /* Keep message on the  */
  821.                         break;                  /* display.             */
  822.                 }
  823.         lp0 = curwp->w_dotp;    /* line previous to insert */
  824.         lp2 = lp0->l_fp;    /* line after insert */
  825.  
  826.         /* re-link new line between lp0 and lp2 */
  827.         lp2->l_bp = lp1;
  828.         lp0->l_fp = lp1;
  829.         lp1->l_bp = lp0;
  830.         lp1->l_fp = lp2;
  831.  
  832.         /* and advance and write out the current line */
  833.         curwp->w_dotp = lp1;
  834.                 for (i=0; i<nbytes; ++i){
  835.             ac.c = line[i];
  836.             lputc(lp1, i, ac);
  837.         }
  838.                 ++nline;
  839.         }
  840.         ffclose();                              /* Ignore errors.       */
  841.     curwp->w_imarkp = lforw(curwp->w_imarkp);
  842.         if (s == FIOEOF) {                      /* Don't zap message!   */
  843.             sprintf(dbuf,"Inserted %d line%s",nline,(nline>1) ? "s" : "");
  844.         emlwrite(dbuf, NULL);
  845.         }
  846.     if (lflag) {
  847.         sprintf(dbuf,"Inserted %d line%s, Long lines wrapped.",
  848.             nline, (nline>1) ? "s" : "");
  849.         emlwrite(dbuf, NULL);
  850.         }
  851. out:
  852.     /* advance to the next line and mark the window for changes */
  853.     curwp->w_flag |= WFHARD;
  854.  
  855.     /* copy window parameters back to the buffer structure */
  856.     curbp->b_dotp = curwp->w_dotp;
  857.     curbp->b_doto = curwp->w_doto;
  858.     curbp->b_markp = curwp->w_imarkp;
  859.     curbp->b_marko = curwp->w_imarko;
  860.  
  861.         if (s == FIOERR)                        /* False if error.      */
  862.                 return (FALSE);
  863.         return (TRUE);
  864. }
  865.  
  866.  
  867.  
  868. /*
  869.  * pico_fncomplete - pico's function to complete the given file name
  870.  */
  871. int pico_fncomplete(dir, fn, len)
  872. char *dir, *fn;
  873. int   len;
  874. {
  875.     char *p, *dlist, tmp[NFILEN], dtmp[NFILEN];
  876.     int   n, i, match = -1;
  877. #ifdef    DOS
  878. #define    FILECMP(x, y)    (toupper(x) == toupper(y))
  879. #else
  880. #define    FILECMP(x, y)    ((x) == (y))
  881. #endif
  882.  
  883.     strcpy(dtmp, dir);
  884.     pfnexpand(dir = dtmp, NFILEN);
  885.     if(*fn && (dlist = p = getfnames(dir, fn, &n, NULL))){
  886.     memset(tmp, 0, sizeof(tmp));
  887.     while(n--){            /* any names in it */
  888.         for(i = 0; fn[i] && FILECMP(p[i], fn[i]); i++)
  889.           ;
  890.  
  891.         if(!fn[i]){            /* match or more? */
  892.         if(tmp[0]){
  893.             for(; p[i] && FILECMP(p[i], tmp[i]); i++)
  894.               ;
  895.  
  896.             match = !p[i] && !tmp[i];
  897.             tmp[i] = '\0';    /* longest common string */
  898.         }
  899.         else{
  900.             match = 1;        /* may be it!?! */
  901.             strcpy(tmp,  p);
  902.         }
  903.         }
  904.  
  905.         p += strlen(p) + 1;
  906.     }
  907.  
  908.     free(dlist);
  909.     }
  910.  
  911.     if(match >= 0){
  912.     strncpy(fn, tmp, len);
  913.     fn[len] = '\0';
  914.     }
  915.  
  916.     return(match == 1);
  917.  
  918. }
  919.  
  920.  
  921. /*
  922.  * in_oper_tree - returns true if file "f" does reside in opertree
  923.  */
  924. in_oper_tree(f)
  925. char *f;
  926. {
  927.     return(!strncmp(opertree, f, strlen(opertree)));
  928. }
  929.